package com.rickpan.service;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.rickpan.dto.request.ReportManageRequest;
import com.rickpan.dto.response.ReportManageResponse;
import com.rickpan.entity.GeneratedReport;
import com.rickpan.exception.BusinessException;
import com.rickpan.repository.GeneratedReportRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import jakarta.persistence.criteria.Predicate;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 报告管理服务
 * 提供报告的查询、编辑、删除、导出等管理功能
 */
@Service
public class ReportManageService {

    private static final Logger logger = LoggerFactory.getLogger(ReportManageService.class);

    @Autowired
    private GeneratedReportRepository generatedReportRepository;

    @Autowired
    private ObjectMapper objectMapper;

    /**
     * 分页查询用户报告列表
     */
    public Page<ReportManageResponse.ReportSummaryResponse> getReportList(Long userId, 
                                                                         ReportManageRequest.ReportQueryRequest request) {
        logger.info("查询用户报告列表，用户ID: {}, 查询条件: {}", userId, request);

        // 构建分页参数
        Sort sort = Sort.by(Sort.Direction.fromString(request.getSortDirection()), request.getSortBy());
        Pageable pageable = PageRequest.of(request.getPage(), request.getSize(), sort);

        // 构建查询条件
        Specification<GeneratedReport> spec = buildQuerySpecification(userId, request);

        // 执行查询
        Page<GeneratedReport> reportPage = generatedReportRepository.findAll(spec, pageable);

        // 转换为响应DTO
        return reportPage.map(report -> {
            ReportManageResponse.ReportSummaryResponse response = new ReportManageResponse.ReportSummaryResponse(report);
            // 解析标签
            response.setTags(parseTagsFromJson(report.getTags()));
            return response;
        });
    }

    /**
     * 获取报告详情
     */
    public ReportManageResponse.ReportDetailResponse getReportDetail(Long userId, Long reportId) {
        logger.info("获取报告详情，用户ID: {}, 报告ID: {}", userId, reportId);

        GeneratedReport report = generatedReportRepository.findById(reportId)
            .orElseThrow(() -> new BusinessException("报告不存在"));

        // 验证用户权限
        if (!report.getUserId().equals(userId)) {
            throw new BusinessException("无权访问该报告");
        }

        ReportManageResponse.ReportDetailResponse response = new ReportManageResponse.ReportDetailResponse(report);
        response.setTags(parseTagsFromJson(report.getTags()));
        return response;
    }

    /**
     * 更新报告
     */
    @Transactional
    public ReportManageResponse.ReportDetailResponse updateReport(Long userId, Long reportId, 
                                                                 ReportManageRequest.ReportUpdateRequest request) {
        logger.info("更新报告，用户ID: {}, 报告ID: {}", userId, reportId);

        GeneratedReport report = generatedReportRepository.findById(reportId)
            .orElseThrow(() -> new BusinessException("报告不存在"));

        // 验证用户权限
        if (!report.getUserId().equals(userId)) {
            throw new BusinessException("无权修改该报告");
        }

        // 更新报告信息
        report.setTitle(request.getTitle());
        report.setEditedContent(request.getEditedContent());
        report.setStatus(request.getStatus());
        
        // 更新标签
        if (request.getTags() != null) {
            report.setTags(convertTagsToJson(request.getTags()));
        }

        // 如果内容有变化，增加版本号
        if (!Objects.equals(report.getEditedContent(), request.getEditedContent())) {
            report.setVersion(report.getVersion() + 1);
        }

        GeneratedReport savedReport = generatedReportRepository.save(report);
        
        ReportManageResponse.ReportDetailResponse response = new ReportManageResponse.ReportDetailResponse(savedReport);
        response.setTags(parseTagsFromJson(savedReport.getTags()));
        return response;
    }

    /**
     * 删除报告
     */
    @Transactional
    public void deleteReport(Long userId, Long reportId) {
        logger.info("删除报告，用户ID: {}, 报告ID: {}", userId, reportId);

        GeneratedReport report = generatedReportRepository.findById(reportId)
            .orElseThrow(() -> new BusinessException("报告不存在"));

        // 验证用户权限
        if (!report.getUserId().equals(userId)) {
            throw new BusinessException("无权删除该报告");
        }

        generatedReportRepository.delete(report);
        logger.info("报告删除成功，报告ID: {}", reportId);
    }

    /**
     * 批量删除报告
     */
    @Transactional
    public void batchDeleteReports(Long userId, List<Long> reportIds) {
        logger.info("批量删除报告，用户ID: {}, 报告数量: {}", userId, reportIds.size());

        // 查询用户的报告
        List<GeneratedReport> reports = generatedReportRepository.findByUserIdAndIdIn(userId, reportIds);
        
        if (reports.size() != reportIds.size()) {
            throw new BusinessException("部分报告不存在或无权访问");
        }

        generatedReportRepository.deleteAll(reports);
        logger.info("批量删除报告成功，删除数量: {}", reports.size());
    }

    /**
     * 获取报告统计信息
     */
    public ReportManageResponse.ReportStatsResponse getReportStats(Long userId) {
        logger.info("获取报告统计信息，用户ID: {}", userId);

        ReportManageResponse.ReportStatsResponse stats = new ReportManageResponse.ReportStatsResponse();

        // 总报告数
        stats.setTotalReports(generatedReportRepository.countByUserId(userId));

        // 各类型报告统计
        List<Object[]> typeStatsData = generatedReportRepository.countByUserIdGroupByType(userId);
        Map<String, Long> typeStats = new HashMap<>();
        for (Object[] row : typeStatsData) {
            GeneratedReport.ReportType type = (GeneratedReport.ReportType) row[0];
            Long count = (Long) row[1];
            typeStats.put(type.name(), count);
        }
        stats.setTypeStats(typeStats);

        // 各状态报告统计
        List<Object[]> statusStatsData = generatedReportRepository.countByUserIdGroupByStatus(userId);
        Map<String, Long> statusStats = new HashMap<>();
        for (Object[] row : statusStatsData) {
            GeneratedReport.ReportStatus status = (GeneratedReport.ReportStatus) row[0];
            Long count = (Long) row[1];
            statusStats.put(status.name(), count);
        }
        stats.setStatusStats(statusStats);

        // 最近7天趋势
        LocalDateTime endTime = LocalDateTime.now();
        LocalDateTime startTime = endTime.minusDays(7);
        List<Object[]> recentTrendData = generatedReportRepository.getReportStatsByDateRange(userId, startTime, endTime);
        List<ReportManageResponse.ReportStatsResponse.DailyStatsItem> recentTrend = recentTrendData.stream()
            .map(row -> {
                LocalDate date;
                if (row[0] instanceof java.sql.Date) {
                    date = ((java.sql.Date) row[0]).toLocalDate();
                } else if (row[0] instanceof LocalDate) {
                    date = (LocalDate) row[0];
                } else {
                    date = LocalDate.now(); // 默认值
                }
                return new ReportManageResponse.ReportStatsResponse.DailyStatsItem(date, (Long) row[1]);
            })
            .collect(Collectors.toList());
        stats.setRecentTrend(recentTrend);

        // 月度趋势
        List<Object[]> monthlyTrendData = generatedReportRepository.getReportTrendsByMonth(userId);
        List<ReportManageResponse.ReportStatsResponse.MonthlyStatsItem> monthlyTrend = monthlyTrendData.stream()
            .map(row -> new ReportManageResponse.ReportStatsResponse.MonthlyStatsItem(
                (Integer) row[0], (Integer) row[1], (Long) row[2]))
            .collect(Collectors.toList());
        stats.setMonthlyTrend(monthlyTrend);

        return stats;
    }

    /**
     * 构建查询条件
     */
    private Specification<GeneratedReport> buildQuerySpecification(Long userId, 
                                                                  ReportManageRequest.ReportQueryRequest request) {
        return (root, query, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();

            // 用户ID条件
            predicates.add(criteriaBuilder.equal(root.get("userId"), userId));

            // 报告类型条件
            if (request.getType() != null) {
                predicates.add(criteriaBuilder.equal(root.get("type"), request.getType()));
            }

            // 报告状态条件
            if (request.getStatus() != null) {
                predicates.add(criteriaBuilder.equal(root.get("status"), request.getStatus()));
            }

            // 关键词搜索条件
            if (request.getKeyword() != null && !request.getKeyword().trim().isEmpty()) {
                String keyword = "%" + request.getKeyword().trim() + "%";
                Predicate titlePredicate = criteriaBuilder.like(root.get("title"), keyword);
                Predicate contentPredicate = criteriaBuilder.like(root.get("originalContent"), keyword);
                Predicate editedContentPredicate = criteriaBuilder.like(root.get("editedContent"), keyword);
                
                predicates.add(criteriaBuilder.or(titlePredicate, contentPredicate, editedContentPredicate));
            }

            // 日期范围条件
            if (request.getStartDate() != null) {
                predicates.add(criteriaBuilder.greaterThanOrEqualTo(root.get("periodStart"), request.getStartDate()));
            }
            if (request.getEndDate() != null) {
                predicates.add(criteriaBuilder.lessThanOrEqualTo(root.get("periodEnd"), request.getEndDate()));
            }

            return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
        };
    }

    /**
     * 解析JSON格式的标签
     */
    private List<String> parseTagsFromJson(String tagsJson) {
        if (tagsJson == null || tagsJson.trim().isEmpty()) {
            return new ArrayList<>();
        }
        
        try {
            return objectMapper.readValue(tagsJson, new TypeReference<List<String>>() {});
        } catch (JsonProcessingException e) {
            logger.warn("解析标签JSON失败: {}", tagsJson, e);
            return new ArrayList<>();
        }
    }

    /**
     * 将标签列表转换为JSON格式
     */
    private String convertTagsToJson(List<String> tags) {
        if (tags == null || tags.isEmpty()) {
            return null;
        }
        
        try {
            return objectMapper.writeValueAsString(tags);
        } catch (JsonProcessingException e) {
            logger.warn("转换标签为JSON失败: {}", tags, e);
            return null;
        }
    }
}
